﻿#pragma once
#include <QAbstractListModel>
#include <QList>
#include <QSet>
#include "XuanCommon_global.h"
///
/// \brief 这是一个抽象模板类
/// 该类是List的抽象类(类似于vector<T>),并实现了相关的list操作方法
/// 模板类要么包含,要么在同文件中实现方法
///
template<class T>
class  QuickListModelBase:public QAbstractListModel
{
public:
    using Super = QAbstractListModel;
    explicit QuickListModelBase(QObject * parent = nullptr);
    explicit QuickListModelBase(const   QList<T> data ,QObject * parent = nullptr);
    virtual ~QuickListModelBase() override;


public:
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    QVariant data(int row) const;
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;

public:
    //重置
    void resetData(const QList<T> &data);

    //get
    const QList<T> &getDatas()const{  return this->m_Data; };
    const QSet<T> &getAllDatas()const{ return this->m_AllData;};

    //添加操作
    void append(const QList<T> &data); //尾部添加
    void insert(int rows,QList<T> &data);//插入
    void prepend(T data); //头部添加

    void clear();
    void removeat(int row);
    void substract(const QSet<T> &other); //移除相同item

    void updateData(int row ,T data);

public :
    //比较数据是否变化
    bool compareDataChanged(const QList<T> &list1,const QList<T>&list2){
        bool changed = false; //该变量记录 数据是否发生变化
        //s1 记录之前的值,s2记录之后的值 然后进行比较
        QSet<T> set1;
        QSet<T>set2;
        for(auto it = list1.begin();it!=list1.end();it++){
            set1.insert(*it);
        }

        for(auto it = list2.begin();it!=list2.end();it++){
            //find用于查询是否存在,不存在返回迭代器的end()
            //如果set1中存在但是set2中不存在,那么说明数据变化了
            if(set1.find(*it) == set1.end()){
                changed = true;
                break;
            }
            set2.insert(*it);
        }

        for(auto it = set1.begin();it!=set1.end();it++){
            if(set2.find(*it) ==set2.end()){
                changed = true;
                break;
            }
        }

        return changed;
    }
    virtual void updateCalInfo(){};
protected:
    //有序,重复序列
    QList<T> m_Data;
    //无序,不重复序列
    QSet<T> m_AllData;
};


template<class T>
QuickListModelBase<T>::QuickListModelBase(QObject * parent):Super(parent)
{

}

template<class T>
QuickListModelBase<T>::QuickListModelBase(const   QList<T> data ,QObject * parent):Super(parent),m_Data(data)
{
    for(auto it = m_Data.begin();it!=m_Data.end();it++){
        m_AllData.insert(*it);
    }
}

template<class T>
QuickListModelBase<T>::~QuickListModelBase(){
    m_Data.clear();
    m_AllData.clear();
}

template<class T>
QVariant QuickListModelBase<T>::data(const QModelIndex &index, int role) const{
    if(index.row()<0 || index.row()>m_Data.size()){
        return QVariant();
    }
    if(role == Qt::DisplayRole || role ==Qt::EditRole){

        auto data = m_Data.at(index.row());
        return QVariant::fromValue(data);
    }
    return QVariant();

}

template<class T>
QVariant QuickListModelBase<T>::data(int row) const{
    return data(index(row),Qt::DisplayRole);
}

template<class T>
int QuickListModelBase<T>::rowCount(const QModelIndex &parent)const{
    return m_Data.count();
}


template<class T>
void QuickListModelBase<T>::resetData(const QList<T> &data){
    auto oldObj = m_AllData;
    m_AllData.clear();
    beginResetModel();
    m_Data = data;
    for(auto it = m_Data.begin(); it!=m_Data.end();it++){
        m_AllData.insert(*it);
    }
    endResetModel();
    qDeleteAll(oldObj);
    updateCalInfo();
}

template<class T>
void QuickListModelBase<T>::append(const QList<T> &data){
    if(data.count()<0){
        return;
    }
    beginInsertRows({},m_Data.count(),m_Data.count()+data.count()-1);
    m_Data.append(data);
    for(auto it = data.begin();it!=data.end();it++){
        m_AllData.insert(*it);
    }
    endInsertRows();
    updateCalInfo();
}

template<class T>
void QuickListModelBase<T>::insert(int rows,QList<T> &data){
    if(rows<0 || rows>m_Data.size()){
        return;
    }

    beginInsertRows({},rows,rows+data.count()-1);
    int index = rows;
    for(const auto &item:data){
        m_Data.insert(index,item);
        m_AllData.insert(item);
        index++;
    }
    endInsertRows();
    updateCalInfo();
}

template<class T>
void QuickListModelBase<T>::prepend(T data){

    beginInsertRows({},0,0);
    m_Data.prepend(data);
    m_AllData.insert(data);
    endInsertRows();
    updateCalInfo();
}

template<class T>
void QuickListModelBase<T>::clear(){
    int dataCount =  m_Data.count();
    if(dataCount>0){
        beginRemoveRows({}, 0, dataCount - 1);
    }
    qDeleteAll(m_AllData);
    m_Data.clear();
    m_AllData.clear();
    if(dataCount>0){
        endRemoveRows();
    }
    updateCalInfo();
}

template<class T>
void QuickListModelBase<T>::removeat(int row){
    if(row<0 || row > m_Data.count()){
        return ;
    }
    beginRemoveRows({}, row, row);
    auto obj =m_Data.at(row);
    m_Data.removeAt(row);
    m_AllData.remove(obj);
    obj->deleteLater();
    endRemoveRows();
    updateCalInfo();
}

template<class T>
void QuickListModelBase<T>::substract(const QSet<T> &other){
    if(other.size() == 0){
        return;
    }
    beginResetModel();
    m_AllData.subtract(other);
    m_Data  =m_AllData.values();
    endResetModel();
    qDeleteAll(other);
    updateCalInfo();
}

template<class T>
void QuickListModelBase<T>::updateData(int row ,T data){
    if(row<0 || row>m_Data.size()){
        return ;
    }
    auto dataobj = m_Data.at(row);
    m_Data[row] = data;
    m_AllData.remove(dataobj);
    m_AllData.insert(data);
    emit dataChanged(index(row,0),index(row,0));
    dataobj.deleteLater();
    updateCalInfo();

}
